package com.zj.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

@Component
public class JwtTokenUtil {
    //从配置文件中获取密钥
    @Value("${token.secret}")
    private String secret;
    //从配置文件中获取过期时间
    @Value("${token.expiration}")
    private Long expiration;

    /**
     * 生成token
     * @param userId
     * @param userName
     * @param roles
     * @return  生成JWT token
     */
    public String generateToken(Long userId, String userName, Set<String> roles){
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId",userId);
        claims.put("userName",userName);
        claims.put("roles",roles);
        return createToken(claims,userName);
    }

    /**
     * 创建token
     * @param claims 负载  自定义声明
     * @param subject 主题
     * @return
     */
    private String createToken(Map<String, Object> claims,String subject) {
        Date now = new Date();
        Date expirationDate = new Date(now.getTime() + expiration);
        return Jwts.builder()
                .setClaims(claims) // 设置自定义声明
                .setSubject(subject) // 设置主题
                .setIssuedAt(now) // 设置签发时间
                .setExpiration(expirationDate) // 设置过期时间
                .signWith(getSigningKey(), SignatureAlgorithm.HS256)  //使用HS256算法和密钥签名
                .compact();
    }

    /**
     * 获取签名密钥
     * @return
     */
    private Key getSigningKey() {
        byte[] keyBytes = Decoders.BASE64.decode(secret);
        return Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 解析token 从token中获取所有的claims
     * @param token
     * @return
     */
    private Claims extractAllClaim(String token) {
        return Jwts.parser()
                .setSigningKey(getSigningKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 从token中获取特定的claim
     * @param token
     * @param claimName
     * @return
     */
    private <T> T extractClaim(String token, Function<Claims, T> claimName) {
        final Claims claims = extractAllClaim(token);
        return claimName.apply(claims);
    }

    /**
     * 从token中获取用户名
     * @param token
     * @return
     */
    public String extractUserName(String token){
        return extractClaim(token, Claims::getSubject);
    }

    /**
     * 从token中获取过期时间
     * @param token
     * @return
     */
    public Date extractExpiration(String token){
        return extractClaim(token, Claims::getExpiration);
    }

    /**
     * 检查token是否过期
     * @param token
     * @return
     */
    public boolean isOK(String token){
        return extractExpiration(token).before(new Date());
    }

    public static void main(String[] args) {
        JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
//        String token = jwtTokenUtil.generateToken(1L, "admin", new HashSet<>(Arrays.asList("admin")));
//        System.out.println(token);
        //eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJhZG1pbiJdLCJ1c2VyTmFtZSI6ImFkbWluIiwidXNlcklkIjoxLCJzdWIiOiJhZG1pbiIsImlhdCI6MTc1NjM1MjI5MiwiZXhwIjoxNzU4OTQ0MjkyfQ.vTX518XDeMfeGQrD1RCmlDeW1nBP5Ig8cQwKIYk-kRQ

        Claims claims = jwtTokenUtil.extractAllClaim("eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJhZG1pbiJdLCJ1c2VyTmFtZSI6ImFkbWluIiwidXNlcklkIjoxLCJzdWIiOiJhZG1pbiIsImlhdCI6MTc1NjM1MjI5MiwiZXhwIjoxNzU4OTQ0MjkyfQ.vTX518XDeMfeGQrD1RCmlDeW1nBP5Ig8cQwKIYk-kRQ");
        System.out.println(claims);

        System.out.println("是否过期"+jwtTokenUtil.isOK("eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJhZG1pbiJdLCJ1c2VyTmFtZSI6ImFkbWluIiwidXNlcklkIjoxLCJzdWIiOiJhZG1pbiIsImlhdCI6MTc1NjM1MjI5MiwiZXhwIjoxNzU4OTQ0MjkyfQ.vTX518XDeMfeGQrD1RCmlDeW1nBP5Ig8cQwKIYk-kRQ"));

        System.out.println("过期时间"+jwtTokenUtil.extractExpiration("eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJhZG1pbiJdLCJ1c2VyTmFtZSI6ImFkbWluIiwidXNlcklkIjoxLCJzdWIiOiJhZG1pbiIsImlhdCI6MTc1NjM1MjI5MiwiZXhwIjoxNzU4OTQ0MjkyfQ.vTX518XDeMfeGQrD1RCmlDeW1nBP5Ig8cQwKIYk-kRQ"));

        System.out.println("用户名"+jwtTokenUtil.extractUserName("eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJhZG1pbiJdLCJ1c2VyTmFtZSI6ImFkbWluIiwidXNlcklkIjoxLCJzdWIiOiJhZG1pbiIsImlhdCI6MTc1NjM1MjI5MiwiZXhwIjoxNzU4OTQ0MjkyfQ.vTX518XDeMfeGQrD1RCmlDeW1nBP5Ig8cQwKIYk-kRQ"));

    }
}
